﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace LightGameLibs
{
    public static class SysEventMgr
    {
        private static Dictionary<int, Action<object, EventArg>> s_eventDict = new Dictionary<int, Action<object, EventArg>>();
        private static Dictionary<int, Action> s_noArgEventDict = new Dictionary<int, Action>();

        public static void AddListenner(int ID, Action act)
        {
            Action targetAct;
            if (!s_noArgEventDict.TryGetValue(ID, out targetAct))
            {
                DebugMgr.Log(DebugTag.EVENT, "NoArgEvent Not Exist, Try To Add:".Add(ID.ToString()));
                var eventAct = new Action(act);
                s_noArgEventDict.Add(ID, eventAct);
                return;
            }

            targetAct += act;
        }

        public static void RemoveListener(int ID, Action act)
        {
            Action targetAct = null;
            if (!s_noArgEventDict.TryGetValue(ID, out targetAct))
            {
                DebugMgr.Log(DebugTag.EVENT, "NoArgEvent Not Exit, Do Nothing:".Add(ID.ToString()));
                return;
            }

            targetAct -= act;

            if (targetAct.GetInvocationList().Length <= 0)
            {
                DebugMgr.Log(DebugTag.EVENT, "NoArgEvent Empty, Remove:".Add(ID.ToString()));
                s_noArgEventDict.Remove(ID);
            }
        }

        public static void AddListenner(int ID, Action<object, EventArg> act)
        {
            Action<object, EventArg> targetAct;
            if (!s_eventDict.TryGetValue(ID, out targetAct))
            {
                DebugMgr.Log(DebugTag.EVENT, "Event Not Exist, Try To Add:".Add(ID.ToString()));
                s_eventDict.Add(ID, act);
                return;
            }

            targetAct += act;
        }

        public static void RemoveListener(int ID, Action<object, EventArg> act)
        {
            Action<object, EventArg> targetAct = null;
            if (!s_eventDict.TryGetValue(ID, out targetAct))
            {
                DebugMgr.Log(DebugTag.EVENT, "Event Not Exit, Do Nothing:".Add(ID.ToString()));
                return;
            }

            targetAct -= act;

            if (targetAct.GetInvocationList().Length <= 0)
            {
                DebugMgr.Log(DebugTag.EVENT, "Event Empty, Remove:".Add(ID.ToString()));
                s_eventDict.Remove(ID);
            }
        }

        public static void Invoke(int ID, object sender, EventArg args)
        {
            Action<object, EventArg> targetAct = null;
            bool isContain = s_eventDict.TryGetValue(ID, out targetAct);
            bool isSenderNull = null == sender;

            if (!isContain)
            {
                DebugMgr.Log(DebugTag.EVENT, "Event Not Exist In EventDict, Do Nothing:".Add(ID.ToString()));
                return;
            }

            if (isSenderNull)
            {
                DebugMgr.Log(DebugTag.EVENT, "EventArg Cannot Be Null:".Add(ID.ToString()));
            }

            if (isContain && !isSenderNull)
            {
                targetAct.Invoke(sender, args);
            }

            Action targetNoArgAct = null;
            if (s_noArgEventDict.TryGetValue(ID, out targetNoArgAct))
            {
                targetNoArgAct.Invoke();
            }
        }

        public static void Invoke(int ID)
        {
            Action targetAct = null;
            if (!s_noArgEventDict.TryGetValue(ID, out targetAct))
            {
                DebugMgr.Log(DebugTag.EVENT, "Event Not Exist In NoArgEventDict, Do Nothing:".Add(ID.ToString()));
                return;
            }

            targetAct.Invoke();
        }
    }
}
